package cn.itsource.user.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.lang.UUID;
import cn.hutool.core.util.RandomUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.crypto.SecureUtil;
import cn.hutool.http.HttpUtil;
import cn.itsource.basic.constant.WxConstants;
import cn.itsource.basic.exception.BusinessException;
import cn.itsource.basic.jwt.JwtUtil;
import cn.itsource.basic.jwt.Payload;
import cn.itsource.basic.service.impl.BaseServiceImpl;
import cn.itsource.basic.utils.AjaxResult;
import cn.itsource.system.domain.Menu;
import cn.itsource.user.domain.Logininfo;
import cn.itsource.user.domain.User;
import cn.itsource.user.domain.Wxuser;
import cn.itsource.user.mapper.LogininfoMapper;
import cn.itsource.user.mapper.UserMapper;
import cn.itsource.user.mapper.WxuserMapper;
import cn.itsource.user.service.LogininfoService;
import com.alibaba.fastjson.JSONObject;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;

import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * 业务实现类：
 */
@Service
public class LogininfoServiceImpl extends BaseServiceImpl<Logininfo> implements LogininfoService {

    @Autowired
    private LogininfoMapper logininfoMapper;
    @Autowired
    private RedisTemplate redisTemplate;
    @Autowired
    private WxuserMapper wxuserMapper;
    @Autowired
    private UserMapper userMapper;

    //账号登录
    @Override
    public AjaxResult accountLogin(Map<String, String> map) {
        //校验空值   account: 'admin',
        //          password: '123456',
        //          type:"0",
        if (StrUtil.isBlank(map.get("account")) || StrUtil.isBlank(map.get("password"))) {
            throw new BusinessException("请填写完整的登录信息");
        }

        //校验登录账号是否存在
        Logininfo logininfo = logininfoMapper.findAccount(map.get("account"), Integer.valueOf(map.get("type")));
        if (logininfo == null) {
            throw new BusinessException("你的登录信息不存在，请注册！！！");
        }

        //校验密码是否正确
        if (!logininfo.getPassword().equals(SecureUtil.md5(map.get("password") + logininfo.getSalt()))) {
            throw new BusinessException("你密码有误，请重新输入！！！");
        }
        //校验禁用状态
        if (logininfo.getState() == 0) {
            throw new BusinessException("你的用户信息被禁用.请联系管理员");
        }
        //创建token ，把登录信息存入redis中
        Map<String, Object> loginMap = loginSuccessJwtHandle(logininfo);
//        String token = IdUtil.randomUUID();
//        redisTemplate.opsForValue().set(token, logininfo, 30, TimeUnit.MINUTES);
//        Map<String, Object> loginMap = new HashMap<>();
//        loginMap.put("token", token);
//        logininfo.setPassword(null);
//        loginMap.put("logininfo", logininfo);
        return AjaxResult.me().setObj(loginMap);

    }

    //微信扫码登录接口
    @Override
    public AjaxResult wechatLogin(String code) {
        //组装ulr
        String url = WxConstants.GET_ACK_URL
                .replace("APPID", WxConstants.APPID)
                .replace("SECRET", WxConstants.SECRET)
                .replace("CODE", code);
        String jsonStr = HttpUtil.get(url); //第二次发送get请求到第三方接口微信，返回jsonString
        JSONObject jsonObject = JSONObject.parseObject(jsonStr);//将json字符串转对象
        /**
         * {
         *   "access_token": "ACCESS_TOKEN",
         *   "expires_in": 7200,
         *   "refresh_token": "REFRESH_TOKEN",
         *   "openid": "OPENID",
         *   "scope": "SCOPE",
         *   "unionid": "UNIONID"
         * }
         */
        String accessToken = jsonObject.getString("access_token"); //接口调用凭证
        String openid = jsonObject.getString("openid"); //授权用户唯一标识
        String token = UUID.randomUUID().toString();  //生产随机字符串 作为token -》uuid，IdUtil,RandomUtil
        Wxuser wxuser = wxuserMapper.findOpenid(openid);
        if (wxuser != null) {
            User user = userMapper.findOne(wxuser.getUserId());
            if (user != null) {
                //禁用的处理
                if (user.getState() == 0) {
                    return AjaxResult.me().setSuccess(false).setMessage("账号异常，请联系管理员");
                }
                Logininfo logininfo = logininfoMapper.findOne(user.getLogininfoId());
                Map<String, Object> map = loginSuccessJwtHandle(logininfo);
//                redisTemplate.opsForValue().set(token, logininfo, 30, TimeUnit.MINUTES); //设置过期时间。
//                HashMap<String, Object> map = new HashMap<>();  //返回给前端存放在localStorage
//                map.put("token", token);
//                logininfo.setPassword(null);
//                map.put("logininfo", logininfo);
                return AjaxResult.me().setObj(map);
            }
        }
        //没有关联跳转手机绑定页面   "?accessToken="+accessToken+"&openId="+openId;
        String params = "?accessToken=" + accessToken + "&openid=" + openid;
        return AjaxResult.me().setMessage(null).setSuccess(false).setObj(params);
    }

    //微信电话绑定
    @Override
    public AjaxResult wechatBinder(Map<String, String> map) {
        String phone = map.get("phone");  //电话号码
        String verifyCode = map.get("verifyCode"); //手机验证码
        String accessToken = map.get("accessToken"); //微信token
        String openid = map.get("openid");  //微信唯一标识
        //校验空值
        if (StrUtil.isBlank(phone) || StrUtil.isBlank(verifyCode)) {
            throw new BusinessException("请输入完整的绑定信息");
        }
        //从redis中获取验证码->获取redis的手机短信验证码【binder:18455669988 - 764347:1715413642524】
        Object obj = redisTemplate.opsForValue().get("binder:" + phone);  //764347:1715413642524
        if (obj == null) {
            throw new BusinessException("你的手机号验证码已过期，请重新点击获取");
        }
        //截取手机验证码  764347
        if (!obj.toString().split(":")[0].equals(verifyCode)) {
            throw new BusinessException("你输入的手机号验证码不正确");
        }

        //组装url地址
        String url = WxConstants.GET_USER_URL
                .replace("ACCESS_TOKEN", accessToken)
                .replace("OPENID", openid);

        String jsonStr = HttpUtil.get(url);  //返回json字符串
        /**
         * {
         *   "openid": "OPENID",
         *   "nickname": "NICKNAME",
         *   "sex": 1,
         *   "province": "PROVINCE",
         *   "city": "CITY",
         *   "country": "COUNTRY",
         *   "headimgurl": "https://thirdwx.qlogo.cn/mmopen/g3MonUZtNHkdmzicIlibx6iaFqAc56vxLSUfpb6n5WKSYVY0ChQKkiaJSgQ1dZuTOgvLLrhJbERQQ4eMsv84eavHiaiceqxibJxCfHe/0",
         *   "privilege": ["PRIVILEGE1", "PRIVILEGE2"],
         *   "unionid": " o6_bmasdasdsad6_2sgVt7hMZOPfL"
         * }
         */
        JSONObject jsonObject = JSONObject.parseObject(jsonStr); //转换为对象

        //添加数据库
        User user = userMapper.findPhone(phone);
        if (user == null) {
            user = jsonObject2user(phone);
            logininfoMapper.delete(Long.valueOf(phone));
            Logininfo logininfo = new Logininfo();
            BeanUtil.copyProperties(user, logininfo);
            logininfo.setType(1); //0管理员，1用户
            logininfoMapper.add(logininfo);
            user.setLogininfoId(logininfo.getId());
            userMapper.add(user);
        } else {
            if (phone.equals(user.getPhone())) {
                throw new BusinessException("该电话号以被绑定，请联系管理员");
            }
            //禁用的处理
            if (user.getState() == 0) {
                throw new BusinessException("账号异常，请联系管理员");
            }

        }

        Wxuser wxuser = wxuserMapper.findOpenid(openid);
        if (wxuser == null) {
            wxuser = jsonObject2wxuser(jsonObject);
            wxuser.setUserId(user.getId());
            wxuserMapper.add(wxuser);
        } else {
            wxuser.setUserId(user.getId());
            wxuserMapper.update(wxuser);
        }

        //免密登录
        Logininfo logininfo = logininfoMapper.findOne(user.getLogininfoId());

        Map<String, Object> resultmap = loginSuccessJwtHandle(logininfo);
//        String token = IdUtil.randomUUID();
//        redisTemplate.opsForValue().set(token, logininfo, 30, TimeUnit.MINUTES); //设置过期时间。
//        HashMap<String, Object> resultmap = new HashMap<>();  //返回给前端存放在localStorage
//        resultmap.put("token", token);
//        logininfo.setPassword(null);
//        resultmap.put("logininfo", logininfo);

        return AjaxResult.me().setObj(resultmap);

    }

    private Map<String, Object> loginSuccessJwtHandle(Logininfo logininfo) {
        Map<String, Object> map = new HashMap<>();
        Payload payload = new Payload();

        payload.setLogininfo(logininfo);
        map.put("logininfo", logininfo);

        //管理员登录
        if (logininfo.getType() == 0) {
            List<String> permissions = logininfoMapper.findPermissionsBYLlogininfoId(logininfo.getId());
            map.put("permissions", permissions);
            payload.setPermissions(permissions);
            List<Menu> menus = logininfoMapper.findMenusBYLlogininfoId(logininfo.getId());
            map.put("menus", menus);
            payload.setMenus(menus);
        }
        String token = JwtUtil.generateToken(payload);
        map.put("token", token);
        return map;
    }


    private User jsonObject2user(String phone) {
        User user = new User();
        user.setUsername(phone);
        user.setPhone(phone);
        String salt = RandomUtil.randomString(32);
        user.setSalt(salt);
        user.setPassword(SecureUtil.md5(RandomUtil.randomString(6)) + salt);
        user.setState(1); //1启用，0禁用
        return user;
    }

    private Wxuser jsonObject2wxuser(JSONObject jsonObject) {
        /**
         * {
         *   "openid": "OPENID",
         *   "nickname": "NICKNAME",
         *   "sex": 1,
         *   "province": "PROVINCE",
         *   "city": "CITY",
         *   "country": "COUNTRY",
         *   "headimgurl": "https://thirdwx.qlogo.cn/mmopen/g3MonUZtNHkdmzicIlibx6iaFqAc56vxLSUfpb6n5WKSYVY0ChQKkiaJSgQ1dZuTOgvLLrhJbERQQ4eMsv84eavHiaiceqxibJxCfHe/0",
         *   "privilege": ["PRIVILEGE1", "PRIVILEGE2"],
         *   "unionid": " o6_bmasdasdsad6_2sgVt7hMZOPfL"
         * }
         */
        Wxuser wxuser = new Wxuser();
        wxuser.setOpenid(jsonObject.getString("openid"));
        wxuser.setNickname(jsonObject.getString("nickname"));
        String address = jsonObject.getString("country") + jsonObject.getString("province") + jsonObject.getString("city");
        wxuser.setAddress(address);
        wxuser.setHeadimgurl(jsonObject.getString("headimgurl"));
        wxuser.setUnionid(jsonObject.getString("unionid"));
        return wxuser;
    }
}
